//
//  RBVerifyInputView.swift
//  PetAPP
//
//  Created by 冉彬 on 2024/1/4.
//

import Foundation
import UIKit
import CoreMedia


public class RBVerifyInputView: UIView {
    
    /// 样式 默认 splitline
    public var style: RBVerifyInputViewStyle = .splitline() {
        didSet {
            refreshUI()
        }
    }
    
    /// 位数 默认 6 位
    public var count: Int = 6 {
        didSet {
            loadItems()
        }
    }
    
    /// item宽度 不设置会根据间距自动计算
    public var itemWidth: CGFloat? {
        didSet {
            refreshUI()
        }
    }
    
    /// item高度 不设置则跟view一样高
    public var itemHeight: CGFloat? {
        didSet {
            refreshUI()
        }
    }
    
    /// 文本是否加密 默认 false
    public var isSecureTextEntry: Bool = false {
        didSet {
            refreshUI()
        }
    }
    
    /// 文本颜色 默认 black
    public var textColor: UIColor = .black {
        didSet {
            refreshUI()
        }
    }
    
    /// 文本字体 默认常规 16
    public var textFont: UIFont = UIFont.systemFont(ofSize: 16, weight: .regular) {
        didSet {
            refreshUI()
        }
    }
    
    /// 光标颜色 默认 blue
    public var cursorColor: UIColor = .blue {
        didSet {
            refreshUI()
        }
    }
    
    /// 光标宽度 默认 1.6
    public var cursorWidth: CGFloat = 1.6 {
        didSet {
            refreshUI()
        }
    }
    
    /// 光标高度 为空则等于字体高度
    public var cursorHeight: CGFloat? {
        didSet {
            refreshUI()
        }
    }
    
    /// 验证码输入完成后的回调闭包，返回参数为验证码
    public var completeHandler: ((_ verifyCode: String) -> Void)!
    
    private var items: [RBVerifyInputItem] = []
    private var isEditing: Bool = false
    /// 连续边框最后一个分割线
    private lazy var continuousLineView: UIView = {
        let view = UIView(frame: CGRect(x: 0, y: 0, width: 1, height: 1))
        return view
    }()
    
    /// 隐藏的输入框
    private lazy var hideTextField: UITextField = {
        let textfield = UITextField()
        self.addSubview(textfield)
        textfield.isHidden = true
        textfield.keyboardType = .numberPad
        textfield.delegate = self
        return textfield
    }()
    
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        loadItems()
    }
    
    public func startEditor() {
        hideTextField.becomeFirstResponder()
    }
    
    /// 设置验证码输入完成后的回调闭包
    public func setCompleteHandler(complete: @escaping (_ verifyCode: String) -> Void) {
        self.completeHandler = complete
    }
    
    /// 加载items
    private func loadItems() {
        items.forEach({$0.removeFromSuperview()})
        items.removeAll()
        self.continuousLineView.removeFromSuperview()
        for _ in 0..<count {
            let item = RBVerifyInputItem(frame: .zero)
            items.append(item)
            self.addSubview(item)
        }
        self.addSubview(self.continuousLineView)
        refreshUI()
    }
    
    private func refreshUI() {
        self.layer.cornerRadius = 0
        self.layer.borderWidth = 0
        self.continuousLineView.isHidden = true
        switch style {
        case .splitline(let lineHeight, let lineRadius, let lineColor, let itemSpacing):
            var X: CGFloat = (itemWidth == nil) ? 0 : (self.bounds.size.width - itemSpacing*CGFloat(count - 1) - itemWidth!*CGFloat(count))/2
            let Y: CGFloat = (itemHeight == nil) ? 0 : (self.bounds.size.height - itemHeight!)/2
            let W: CGFloat = itemWidth ?? (self.bounds.size.width - itemSpacing*CGFloat(count - 1))/CGFloat(count)
            let H: CGFloat = itemHeight ?? self.bounds.size.height
            for item in items {
                item.frame = CGRect(x: X, y: Y, width: W, height: H)
                item.font = textFont
                item.textColor = textColor
                item.isSecureTextEntry = isSecureTextEntry
                item.cursorColor = cursorColor
                item.cursorWidth = cursorWidth
                item.cursorHeight = cursorHeight
                item.backgroundColor = .clear
                item.rbv_borderColor = .clear
                item.rbv_cornerRadius = 0
                item.lineHeight = lineHeight
                item.lineRadius = lineRadius
                item.lineViewColor = lineColor
                item.isShowlineView = true
                X += W + itemSpacing
            }
        case .splitblock(let borderWidth, let borderRadius, let borderColor, _, let itemBackgroundColor, _, let itemSpacing, let isContinuous):
            self.continuousLineView.isHidden = !isContinuous
            let sp = isContinuous ? 0 : itemSpacing
            var X: CGFloat = (itemWidth == nil) ? 0 : (self.bounds.size.width - sp*CGFloat(count - 1) - itemWidth!*CGFloat(count))/2
            let Y: CGFloat = (itemHeight == nil) ? 0 : (self.bounds.size.height - itemHeight!)/2
            var W: CGFloat = itemWidth ?? (self.bounds.size.width - sp*CGFloat(count - 1))/CGFloat(count)
            if isContinuous {
                W = (self.bounds.size.width + borderWidth * CGFloat(count - 1))/CGFloat(count)
            }
            let H: CGFloat = itemHeight ?? self.bounds.size.height
            for (index, item) in items.enumerated() {
                item.frame = CGRect(x: X, y: Y, width: W, height: H)
                item.font = textFont
                item.textColor = textColor
                item.isSecureTextEntry = isSecureTextEntry
                item.cursorColor = cursorColor
                item.cursorWidth = cursorWidth
                item.cursorHeight = cursorHeight
                item.isShowlineView = false
                item.backgroundColor = itemBackgroundColor
                item.rbv_borderColor = borderColor
                item.rbv_cornerRadius = isContinuous ? 0 : borderRadius
                item.rbv_cornerWidth = borderWidth
                if (index == 0 || index == items.count - 1) && isContinuous {
                    item.rbv_borderColor = .clear
                    item.rbv_cornerWidth = 0
                }
                if index == items.count - 1 {
                    self.continuousLineView.backgroundColor = borderColor
                    let frame = CGRect(x: X, y: Y, width: borderWidth, height: H)
                    self.continuousLineView.frame = frame
                }
                X += W + itemSpacing - (isContinuous ? borderWidth : 0)
            }
            if isContinuous {
                self.layer.cornerRadius = borderRadius
                self.layer.borderColor = borderColor.cgColor
                self.layer.borderWidth = borderWidth
            }
        }
        refreItemUI()
    }
    
    required init(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    /// 刷新Item
    private func refreItemUI() {
        var index = 0
        if items.count == 0 {
            return
        }
        for view in items {
            if view.text?.count ?? 0 > 0 {
                index  = index + 1
            }
            switch style {
            case .splitline(_, _, _, _):
                break
            case .splitblock(_, _, let borderColor, _, let itemBackgroundColor, _, _, _):
                view.rbv_borderColor = borderColor
                view.backgroundColor = itemBackgroundColor
            }
            view.isShowCursor = false
        }
        if index >= items.count {
            return
        }
        switch style {
        case .splitline(_, _, _, _):
            break
        case .splitblock(_, _, _, let borderHighlightedColor, _, let itemBackgroundHighlightedColor, _, _):
            items[index].rbv_borderColor = borderHighlightedColor
            items[index].backgroundColor = itemBackgroundHighlightedColor
        }
        if isEditing {
            items[index].isShowCursor = true
        }
        
    }
    
    
    public override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        hideTextField.becomeFirstResponder()
    }
    
    
}

extension RBVerifyInputView: UITextFieldDelegate {
    
    public func textFieldDidChangeSelection(_ textField: UITextField) {
        guard textField.text!.count <= count else {
            textField.text = String(textField.text!.prefix(count))
            return
        }
        var index = 0
        for char in textField.text! {
            let newText = String(char)
            items[index].text = newText.rb_isNumber() ? newText : newText
            index += 1
        }
        guard index < count else {
            refreItemUI()
            self.endEditing(true)
            if let complete = self.completeHandler {
                complete(textField.text!)
            }
            return
        }
        for i in Range(index...count - 1) {
            items[i].text = ""
        }
        refreItemUI()
    }
    
    public func textFieldDidBeginEditing(_ textField: UITextField) {
        isEditing = true
        refreItemUI()
    }
    
    public func textFieldDidEndEditing(_ textField: UITextField) {
        isEditing = false
        refreItemUI()
    }
    
}



class RBVerifyInputItem: UITextField {
    
    // 边框颜色
    var rbv_borderColor: UIColor = .lightGray {
        didSet {
            self.layer.borderColor = rbv_borderColor.cgColor
        }
    }
    
    // 圆角
    var rbv_cornerRadius: CGFloat = 4 {
        didSet {
            self.layer.cornerRadius = rbv_cornerRadius
        }
    }
    
    // 边框宽
    var rbv_cornerWidth: CGFloat = 1 {
        didSet {
            self.layer.borderWidth = rbv_cornerWidth
        }
    }
    
    
    
    // 是否显示光标
    var isShowCursor: Bool = false {
        didSet {
            refreshCursor()
            if isShowCursor {
                showCursor()
            } else {
                hideCursor()
            }
        }
    }
    
    // 光标颜色
    var cursorColor: UIColor = .black {
        didSet {
            refreshCursor()
        }
    }
    
    var cursorWidth: CGFloat? {
        didSet {
            refreshCursor()
        }
    }
    
    var cursorHeight: CGFloat? {
        didSet {
            refreshCursor()
        }
    }
    
    var isShowlineView: Bool = false {
        didSet {
            refreshLineView()
        }
    }
    
    var lineViewColor: UIColor = .lightGray {
        didSet {
            refreshLineView()
        }
    }
    
    var lineHeight: CGFloat = 1 {
        didSet {
            refreshLineView()
        }
    }
    
    var lineRadius: CGFloat = 0.5 {
        didSet {
            refreshLineView()
        }
    }
    
    override var frame: CGRect {
        didSet {
            refreshCursor()
            refreshLineView()
        }
    }
    
    
    // 光标
    private let cursorLayer = CALayer()
    private lazy var lineView: UIView = {
        let view = UIView(frame: .zero)
        return view
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupUI()
        addNoti()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupUI()
        addNoti() 
    }
    
    deinit {
        // 移除通知观察者
        NotificationCenter.default.removeObserver(self)
    }
    
    func addNoti() {
        // 添加通知观察者(app进入前台，解决app进入后台后再回来动画停止的问题)
        NotificationCenter.default.addObserver(self, selector: #selector(restartAnimation), name: UIApplication.willEnterForegroundNotification, object: nil)
    }
    
    @objc func restartAnimation() {
        // 收到通知后重新启动动画
        if isShowCursor {
            showCursor()
        } else {
            hideCursor()
        }
    }
    
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)
    }
    
    
    /// 初始化UI
    func setupUI() {
        self.layer.cornerRadius = 4
        self.layer.borderColor = UIColor.lightGray.cgColor
        self.layer.borderWidth = 1
        self.textAlignment = .center
        self.font = UIFont.systemFont(ofSize: 16)
        self.textColor = .black
        self.layer.addSublayer(cursorLayer)
        self.isEnabled = false
        self.addSubview(lineView)
    }
    
    /// 刷新光标
    func refreshCursor() {
        cursorLayer.backgroundColor = cursorColor.cgColor
        let cursorWidth1: CGFloat = cursorWidth ?? 1.6
        let cursorHeight1 = cursorHeight ?? self.font?.pointSize ?? 16
        cursorLayer.frame = CGRect(x: (bounds.size.width - cursorWidth1)/2, y: (bounds.size.height - cursorHeight1)/2, width: cursorWidth1, height: cursorHeight1)
    }
    
    /// 刷新下划线
    func refreshLineView() {
        lineView.isHidden = !isShowlineView
        if !isShowlineView { return }
        lineView.frame = CGRect(x: 0, y: bounds.size.height - lineHeight, width: bounds.size.width, height: lineHeight)
        lineView.layer.cornerRadius = lineRadius
        lineView.layer.masksToBounds = true
        lineView.backgroundColor = lineViewColor
    }
    
    
    func showCursor() {
        // 添加光标的闪烁动画
        let animation = CABasicAnimation(keyPath: "opacity")
        animation.fromValue = 1
        animation.toValue = 0
        animation.duration = 0.6
        animation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
        animation.autoreverses = true
        animation.repeatCount = Float.infinity
        cursorLayer.add(animation, forKey: "cursorBlinkAnimation")
        cursorLayer.isHidden = false
    }
    
    func hideCursor() {
        // 移除光标的闪烁动画
        cursorLayer.removeAnimation(forKey: "cursorBlinkAnimation")
        cursorLayer.isHidden = true
    }
    
    
}


public enum RBVerifyInputViewStyle {
    /// 分割下划线
    /// lineHeight: 下划线高
    /// lineRadius：下划线圆角
    /// lineColor：下划线颜色
    /// itemSpacing：item间距
    case splitline(lineHeight: CGFloat = 1, lineRadius: CGFloat = 0.5, lineColor: UIColor = .lightGray, itemSpacing: CGFloat = 10)
    /// 分割块
    /// borderWidth: 边框宽
    /// borderRadius: 边框圆角
    /// borderColor: 边框颜色
    /// borderHighlightedColor: 边框高亮颜色
    /// itemBackgroundColor: item背景颜色
    /// itemBackgroundHighlightedColor: item背景高亮颜色
    /// itemSpacing: item间距
    /// isContinuous: 是否连续，如果是连续的话，itemSpacing将失效
    case splitblock(borderWidth: CGFloat = 1, borderRadius: CGFloat = 6, borderColor: UIColor = .lightGray, borderHighlightedColor: UIColor = .black, itemBackgroundColor: UIColor = .white, itemBackgroundHighlightedColor: UIColor = .white, itemSpacing: CGFloat = 10, isContinuous: Bool = false)
//    /// 连续边框
//    case followborder
}

extension String {
    
    func rb_isNumber() -> Bool {
        let numRegex = "\\d$"
        let numTest = NSPredicate(format: "SELF MATCHES %@", numRegex)
        return numTest.evaluate(with:self)
    }
}
